﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GDI_应用案例
{
    public class StringWrapper
    {
        public StringWrapper(string value)
        {
            this.Value = value ?? string.Empty;
        }
        public StringWrapper(StringWrapper value)
        {
            this.Value = value?.Value ?? string.Empty;
        }
        public string Value { get; private set; }
        public int Length => Value.Length;

        #region 原字符串的操作
        public StringWrapper Substring(int startIndex, int length)
        {
            if (startIndex < 0 || startIndex >= Value.Length)
                throw new ArgumentOutOfRangeException(nameof(startIndex), "起始索引超出字符串范围");
            if (length < 0 || startIndex + length > Value.Length)
                throw new ArgumentOutOfRangeException(nameof(length), "长度超出字符串范围");

            return new StringWrapper(Value.Substring(startIndex, length));
        }
        public int IndexOf(string value)
        {
            if (value == null)
                throw new ArgumentNullException(nameof(value), "查找的字符串不能为空");

            return Value.IndexOf(value);
        }

        public int LastIndexOf(string value)
        {
            if (value == null)
                throw new ArgumentNullException(nameof(value), "查找的字符串不能为空");

            return Value.LastIndexOf(value);
        }
        public StringWrapper Replace(string oldValue, string newValue)
        {
            if (oldValue == null)
                throw new ArgumentNullException(nameof(oldValue), "旧值不能为空");

            return new StringWrapper(Value.Replace(oldValue, newValue ?? string.Empty));
        }
        public StringWrapper[] Split(params char[] separator)
        {
            return Value.Split(separator).Select(s => new StringWrapper(s)).ToArray();
        }
        public static StringWrapper Concat(params StringWrapper[] values)
        {
            if (values == null)
                throw new ArgumentNullException(nameof(values), "参数不能为空");

            return new StringWrapper(string.Concat(values.Select(v => v?.Value ?? string.Empty)));
        }
        public StringWrapper ToUpper()
        {
            return new StringWrapper(Value.ToUpper());
        }

        public StringWrapper ToLower()
        {
            return new StringWrapper(Value.ToLower());
        }
        public StringWrapper Trim()
        {
            return new StringWrapper(Value.Trim());
        }

        public StringWrapper TrimStart(params char[] trimChars)
        {
            return new StringWrapper(Value.TrimStart(trimChars));
        }

        public StringWrapper TrimEnd(params char[] trimChars)
        {
            return new StringWrapper(Value.TrimEnd(trimChars));
        }
        public int CompareTo(StringWrapper other)
        {
            if (other == null)
                throw new ArgumentNullException(nameof(other), "比较对象不能为空");

            return string.Compare(Value, other.Value);
        }
        public static StringWrapper Format(string format, params object[] args)
        {
            if (format == null)
                throw new ArgumentNullException(nameof(format), "格式化字符串不能为空");

            return new StringWrapper(string.Format(format, args));
        }
        public bool Contains(string value)
        {
            if (value == null)
                throw new ArgumentNullException(nameof(value), "查找的字符串不能为空");

            return Value.Contains(value);
        }
        public StringWrapper Insert(int startIndex, string value)
        {
            if (startIndex < 0 || startIndex > Value.Length)
                throw new ArgumentOutOfRangeException(nameof(startIndex), "起始索引超出字符串范围");
            if (value == null)
                throw new ArgumentNullException(nameof(value), "插入的字符串不能为空");

            return new StringWrapper(Value.Insert(startIndex, value));
        }
        public StringWrapper Remove(int startIndex, int length)
        {
            if (startIndex < 0 || startIndex >= Value.Length)
                throw new ArgumentOutOfRangeException(nameof(startIndex), "起始索引超出字符串范围");
            if (length < 0 || startIndex + length > Value.Length)
                throw new ArgumentOutOfRangeException(nameof(length), "长度超出字符串范围");

            return new StringWrapper(Value.Remove(startIndex, length));
        }
        public StringWrapper Reverse()
        {
            return new StringWrapper(new string(Value.Reverse().ToArray()));
        }
        public bool StartsWith(string value)
        {
            if (value == null)
                throw new ArgumentNullException(nameof(value), "查找的字符串不能为空");

            return Value.StartsWith(value);
        }

        public bool EndsWith(string value)
        {
            if (value == null)
                throw new ArgumentNullException(nameof(value), "查找的字符串不能为空");

            return Value.EndsWith(value);
        }
        public bool IsNullOrEmpty()
        {
            return string.IsNullOrEmpty(Value);
        }

        public bool IsNullOrWhiteSpace()
        {
            return string.IsNullOrWhiteSpace(Value);
        }
        public char[] ToCharArray()
        {
            return Value.ToCharArray();
        }
        public string FormatWith(params object[] args)
        {
            return string.Format(Value, args);
        }
        public byte[] GetBytes(Encoding encoding)
        {
            if (encoding == null)
                throw new ArgumentNullException(nameof(encoding), "编码不能为空");

            return encoding.GetBytes(Value);
        }
        #endregion

        public char this[int index]
        {
            get
            {
                // 检查索引是否越界
                if (index < 0 || index >= Value.Length)
                    throw new ArgumentOutOfRangeException(nameof(index), "索引超出字符串范围");
                return Value[index];
            }
            set
            {
                if (index < 0 || index >= Value.Length)
                    throw new ArgumentOutOfRangeException(nameof(index), "索引超出字符串范围");

                char[] chars = Value.ToCharArray();
                chars[index] = value;
                Value = new string(chars);
            }
        }
        public static bool operator <(StringWrapper a, StringWrapper b)
        {
            if (a == null || b == null)
                throw new ArgumentNullException("操作数不能为空");

            return string.Compare(a.Value, b.Value) < 0;
        }
        public static bool operator >(StringWrapper a, StringWrapper b)
        {
            if (a == null || b == null)
                throw new ArgumentNullException("操作数不能为空");

            return string.Compare(a.Value, b.Value) > 0;
        }
        public static StringWrapper operator +(StringWrapper a, StringWrapper b)
        {
            if (a == null && b == null)
                throw new ArgumentNullException("两个操作数不能同时为空");

            return new StringWrapper((a?.Value ?? string.Empty) + (b?.Value ?? string.Empty));
        }
        public static StringWrapper operator -(StringWrapper a, StringWrapper b)
        {
            if (a == null || b == null)
                throw new ArgumentNullException("操作数不能为空");

            string result = a.Value.Replace(b.Value, string.Empty);
            return new StringWrapper(result);
        }
        public static StringWrapper operator !(StringWrapper a)
        {
            if (a == null)
                throw new ArgumentNullException(nameof(a), "StringWrapper 对象不能为空");
            return new StringWrapper(new string(a.Value.Reverse().ToArray()));
        }
        public static StringWrapper operator ++(StringWrapper a)
        {
            if (a == null)
                throw new ArgumentNullException(nameof(a), "StringWrapper 对象不能为空");

            return new StringWrapper(a + a);
        }
        public static StringWrapper operator --(StringWrapper a)
        {
            if (a == null)
                throw new ArgumentNullException(nameof(a), "StringWrapper 对象不能为空");

            return new StringWrapper(a - a);
        }
        public static bool operator true(StringWrapper a)
        {
            if (a == null)
                throw new ArgumentNullException(nameof(a), "StringWrapper 对象不能为空");
            return !string.IsNullOrEmpty(a.Value);
        }
        public static bool operator false(StringWrapper a)
        {
            if (a == null)
                throw new ArgumentNullException(nameof(a), "StringWrapper 对象不能为空");
            return string.IsNullOrEmpty(a.Value);
        }
        public static StringWrapper operator *(StringWrapper a, int times)
        {
            if (a == null)
                throw new ArgumentNullException(nameof(a), "StringWrapper 对象不能为空");
            if (times < 0)
                throw new ArgumentNullException(nameof(times), "times 数量为非负数");

            if (times == 0)
                return new StringWrapper(string.Empty);

            string result = string.Concat(System.Linq.Enumerable.Repeat(a.Value, times));
            return new StringWrapper(result);
        }

        public static bool operator ==(StringWrapper a, StringWrapper b)
        {
            if (ReferenceEquals(a, b)) return true;
            if (a is null || b is null) return false;
            return a.Value == b.Value;
        }

        public static bool operator !=(StringWrapper a, StringWrapper b)
        {
            return !(a == b);
        }

        public static implicit operator StringWrapper(string value)
        {
            return new StringWrapper(value ?? string.Empty);
        }

        public static explicit operator string(StringWrapper obj)
        {
            if (obj == null)
                throw new ArgumentNullException(nameof(obj), "StringWrapper 对象不能为空");
            return obj.Value;
        }

        public override bool Equals(object obj)
        {
            if (obj is StringWrapper other)
                return Value == other.Value;
            return false;
        }

        public override int GetHashCode()
        {
            return Value.GetHashCode();
        }

        public override string ToString()
        {
            return Value;
        }
    }
}
